﻿#include "RandomAccessFile.h"
#include "util/Util.h"

using namespace yzrilyzr_array;
using namespace yzrilyzr_util;
using namespace yzrilyzr_lang;

namespace yzrilyzr_io{
	RandomAccessFile::RandomAccessFile(const String & file, const String & mode){
		open(file, mode);
	}
	RandomAccessFile::RandomAccessFile(const File & file, const String & mode){
		open(file.getAbsolutePath(), mode);
	}
	void RandomAccessFile::checkOpen(){
		if(!fst.is_open()){
			throw IOException("Failed to open file");
		}
	}
	void RandomAccessFile::open(const String & fileName, const String & mode){
		filePath=fileName;
		const char * cstr=fileName.c_str();
		if(mode == "r"){
			fst.open(cstr, std::ios_base::in | std::ios_base::binary);
		} else if(mode == "rw"){
			fst.open(cstr, std::ios_base::in | std::ios_base::out | std::ios_base::binary);
			if(!fst.is_open()){
				fst.open(cstr, std::ios_base::out | std::ios_base::binary);
				fst.close();
				fst.open(cstr, std::ios_base::in | std::ios_base::out | std::ios_base::binary);
			}
		} else{
			throw IOException("Invalid mode");
		}
		checkOpen();
		seek(0);
	}
	u_index RandomAccessFile::getFilePointer(){
		checkOpen();
		return fst.tellg();
	}
	u_index RandomAccessFile::length(){
		checkOpen();
		std::streampos currentPos=fst.tellg();
		fst.seekg(0, std::ios::end);
		std::streampos endPos=fst.tellg();
		fst.seekg(currentPos);
		return static_cast<u_index>(endPos);
	}

	void RandomAccessFile::seek(u_index pos){
		fst.seekg(pos);
		fst.seekp(pos);
	}
	void RandomAccessFile::readFully(ByteArray & b, u_index off, u_index len){
		u_index n=0;
		while(n < len){
			u_index count=read(b, off + n, len - n);
			if(count < 0)
				throw EOFException();
			n+=count;
		}
	}
	u_index RandomAccessFile::skipBytes(u_index n){
		u_index pos;
		u_index len;
		u_index newpos;
		if(n <= 0){
			return 0;
		}
		pos=getFilePointer();
		len=length();
		newpos=pos + n;
		if(newpos > len){
			newpos=len;
		}
		seek(newpos);
		return newpos - pos;
	}
	void RandomAccessFile::write(int32_t b){
		checkOpen();
		char c=static_cast<char>(b & 0xff);
		fst.write(&c, 1);
	}
	void RandomAccessFile::write(const ByteArray & b){
		write(b, 0, b.length);
	}
	void RandomAccessFile::write(const ByteArray & b, u_index off, u_index len){
		checkOpen();
		Util::checkRange(b.length, off, off + len);
		fst.write(reinterpret_cast<const char *>(b._array + off), len);
	}
	int32_t RandomAccessFile::read(){
		checkOpen();
		char c=0;
		fst.read(&c, 1);
		return c;
	}
	u_index RandomAccessFile::read(ByteArray & b){
		return read(b, 0, b.length);
	}
	u_index RandomAccessFile::read(ByteArray & b, u_index off, u_index len){
		checkOpen();
		Util::checkRange(b.length, off, off + len);
		char * buffer=reinterpret_cast<char *>(b._array + off);
		fst.read(buffer, len);
		return fst.gcount(); // 返回读取的字节数
	}
	void RandomAccessFile::close(){
		if(fst.is_open()){
			fst.close();
		}
	}
}